home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / amiga / gui / x / twm93053.lha / twm / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-30  |  22.1 KB  |  894 lines

  1. /*****************************************************************************/
  2. /**       Copyright 1988 by Evans & Sutherland Computer Corporation,        **/
  3. /**                          Salt Lake City, Utah                           **/
  4. /**  Portions Copyright 1989 by the Massachusetts Institute of Technology   **/
  5. /**                        Cambridge, Massachusetts                         **/
  6. /**                                                                         **/
  7. /**                           All Rights Reserved                           **/
  8. /**                                                                         **/
  9. /**    Permission to use, copy, modify, and distribute this software and    **/
  10. /**    its documentation  for  any  purpose  and  without  fee is hereby    **/
  11. /**    granted, provided that the above copyright notice appear  in  all    **/
  12. /**    copies and that both  that  copyright  notice  and  this  permis-    **/
  13. /**    sion  notice appear in supporting  documentation,  and  that  the    **/
  14. /**    names of Evans & Sutherland and M.I.T. not be used in advertising    **/
  15. /**    in publicity pertaining to distribution of the  software  without    **/
  16. /**    specific, written prior permission.                                  **/
  17. /**                                                                         **/
  18. /**    EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD    **/
  19. /**    TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES  OF  MERCHANT-    **/
  20. /**    ABILITY  AND  FITNESS,  IN  NO  EVENT SHALL EVANS & SUTHERLAND OR    **/
  21. /**    M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL  DAM-    **/
  22. /**    AGES OR  ANY DAMAGES WHATSOEVER  RESULTING FROM LOSS OF USE, DATA    **/
  23. /**    OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER    **/
  24. /**    TORTIOUS ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE    **/
  25. /**    OR PERFORMANCE OF THIS SOFTWARE.                                     **/
  26. /*****************************************************************************/
  27.  
  28.  
  29. /***********************************************************************
  30.  *
  31.  * $XConsortium: util.c,v 1.47 91/07/14 13:40:37 rws Exp $
  32.  *
  33.  * utility routines for twm
  34.  *
  35.  * 28-Oct-87 Thomas E. LaStrange    File created
  36.  *
  37.  ***********************************************************************/
  38.  
  39. #include "twm.h"
  40. #include "util.h"
  41. #include "gram.h"
  42. #include "screen.h"
  43. #include <X11/Xos.h>
  44. #include <X11/Xatom.h>
  45. #include <stdio.h>
  46. #include <X11/Xmu/Drawing.h>
  47. #include <X11/Xmu/CharSet.h>
  48.  
  49. static Pixmap CreateXLogoPixmap(), CreateResizePixmap();
  50. static Pixmap CreateQuestionPixmap(), CreateMenuPixmap();
  51. static Pixmap CreateDotPixmap();
  52. int HotX, HotY;
  53.  
  54. /***********************************************************************
  55.  *
  56.  *  Procedure:
  57.  *    MoveOutline - move a window outline
  58.  *
  59.  *  Inputs:
  60.  *    root        - the window we are outlining
  61.  *    x        - upper left x coordinate
  62.  *    y        - upper left y coordinate
  63.  *    width        - the width of the rectangle
  64.  *    height        - the height of the rectangle
  65.  *      bw          - the border width of the frame
  66.  *      th          - title height
  67.  *
  68.  ***********************************************************************
  69.  */
  70.  
  71. /* ARGSUSED */
  72. void MoveOutline(root, x, y, width, height, bw, th)
  73.     Window root;
  74.     int x, y, width, height, bw, th;
  75. {
  76.     static int    lastx = 0;
  77.     static int    lasty = 0;
  78.     static int    lastWidth = 0;
  79.     static int    lastHeight = 0;
  80.     static int    lastBW = 0;
  81.     static int    lastTH = 0;
  82.     int        xl, xr, yt, yb, xinnerl, xinnerr, yinnert, yinnerb;
  83.     int        xthird, ythird;
  84.     XSegment    outline[18];
  85.     register XSegment    *r;
  86.  
  87.     if (x == lastx && y == lasty && width == lastWidth && height == lastHeight
  88.     && lastBW == bw && th == lastTH)
  89.     return;
  90.     
  91.     r = outline;
  92.  
  93. #define DRAWIT() \
  94.     if (lastWidth || lastHeight)            \
  95.     {                            \
  96.     xl = lastx;                    \
  97.     xr = lastx + lastWidth - 1;            \
  98.     yt = lasty;                    \
  99.     yb = lasty + lastHeight - 1;            \
  100.     xinnerl = xl + lastBW;                \
  101.     xinnerr = xr - lastBW;                \
  102.     yinnert = yt + lastTH + lastBW;            \
  103.     yinnerb = yb - lastBW;                \
  104.     xthird = (xinnerr - xinnerl) / 3;        \
  105.     ythird = (yinnerb - yinnert) / 3;        \
  106.                             \
  107.     r->x1 = xl;                    \
  108.     r->y1 = yt;                    \
  109.     r->x2 = xr;                    \
  110.     r->y2 = yt;                    \
  111.     r++;                        \
  112.                             \
  113.     r->x1 = xl;                    \
  114.     r->y1 = yb;                    \
  115.     r->x2 = xr;                    \
  116.     r->y2 = yb;                    \
  117.     r++;                        \
  118.                             \
  119.     r->x1 = xl;                    \
  120.     r->y1 = yt;                    \
  121.     r->x2 = xl;                    \
  122.     r->y2 = yb;                    \
  123.     r++;                        \
  124.                             \
  125.     r->x1 = xr;                    \
  126.     r->y1 = yt;                    \
  127.     r->x2 = xr;                    \
  128.     r->y2 = yb;                    \
  129.     r++;                        \
  130.                             \
  131.     r->x1 = xinnerl + xthird;            \
  132.     r->y1 = yinnert;                \
  133.     r->x2 = r->x1;                    \
  134.     r->y2 = yinnerb;                \
  135.     r++;                        \
  136.                             \
  137.     r->x1 = xinnerl + (2 * xthird);            \
  138.     r->y1 = yinnert;                \
  139.     r->x2 = r->x1;                    \
  140.     r->y2 = yinnerb;                \
  141.     r++;                        \
  142.                             \
  143.     r->x1 = xinnerl;                \
  144.     r->y1 = yinnert + ythird;            \
  145.     r->x2 = xinnerr;                \
  146.     r->y2 = r->y1;                    \
  147.     r++;                        \
  148.                             \
  149.     r->x1 = xinnerl;                \
  150.     r->y1 = yinnert + (2 * ythird);            \
  151.     r->x2 = xinnerr;                \
  152.     r->y2 = r->y1;                    \
  153.     r++;                        \
  154.                             \
  155.     if (lastTH != 0) {                \
  156.         r->x1 = xl;                    \
  157.         r->y1 = yt + lastTH;            \
  158.         r->x2 = xr;                    \
  159.         r->y2 = r->y1;                \
  160.         r++;                    \
  161.     }                        \
  162.     }
  163.  
  164.     /* undraw the old one, if any */
  165.     DRAWIT ();
  166.  
  167.     lastx = x;
  168.     lasty = y;
  169.     lastWidth = width;
  170.     lastHeight = height;
  171.     lastBW = bw;
  172.     lastTH = th;
  173.  
  174.     /* draw the new one, if any */
  175.     DRAWIT ();
  176.  
  177. #undef DRAWIT
  178.  
  179.  
  180.     if (r != outline)
  181.     {
  182.     XDrawSegments(dpy, root, Scr->DrawGC, outline, r - outline);
  183.     }
  184. }
  185.  
  186. /***********************************************************************
  187.  *
  188.  *  Procedure:
  189.  *    Zoom - zoom in or out of an icon
  190.  *
  191.  *  Inputs:
  192.  *    wf    - window to zoom from
  193.  *    wt    - window to zoom to
  194.  *
  195.  ***********************************************************************
  196.  */
  197.  
  198. void
  199. Zoom(wf, wt)
  200.     Window wf, wt;
  201. {
  202.     int fx, fy, tx, ty;            /* from, to */
  203.     unsigned int fw, fh, tw, th;    /* from, to */
  204.     long dx, dy, dw, dh;
  205.     long z;
  206.     int j;
  207.  
  208.     if (!Scr->DoZoom || Scr->ZoomCount < 1) return;
  209.  
  210.     if (wf == None || wt == None) return;
  211.  
  212.     XGetGeometry (dpy, wf, &JunkRoot, &fx, &fy, &fw, &fh, &JunkBW, &JunkDepth);
  213.     XGetGeometry (dpy, wt, &JunkRoot, &tx, &ty, &tw, &th, &JunkBW, &JunkDepth);
  214.  
  215.     dx = ((long) (tx - fx));    /* going from -> to */
  216.     dy = ((long) (ty - fy));    /* going from -> to */
  217.     dw = ((long) (tw - fw));    /* going from -> to */
  218.     dh = ((long) (th - fh));    /* going from -> to */
  219.     z = (long) (Scr->ZoomCount + 1);
  220.  
  221.     for (j = 0; j < 2; j++) {
  222.     long i;
  223.  
  224.     XDrawRectangle (dpy, Scr->Root, Scr->DrawGC, fx, fy, fw, fh);
  225.     for (i = 1; i < z; i++) {
  226.         int x = fx + (int) ((dx * i) / z);
  227.         int y = fy + (int) ((dy * i) / z);
  228.         unsigned width = (unsigned) (((long) fw) + (dw * i) / z);
  229.         unsigned height = (unsigned) (((long) fh) + (dh * i) / z);
  230.     
  231.         XDrawRectangle (dpy, Scr->Root, Scr->DrawGC,
  232.                 x, y, width, height);
  233.     }
  234.     XDrawRectangle (dpy, Scr->Root, Scr->DrawGC, tx, ty, tw, th);
  235.     }
  236. }
  237.  
  238.  
  239. /***********************************************************************
  240.  *
  241.  *  Procedure:
  242.  *    ExpandFilename - expand the tilde character to HOME
  243.  *        if it is the first character of the filename
  244.  *
  245.  *  Returned Value:
  246.  *    a pointer to the new name
  247.  *
  248.  *  Inputs:
  249.  *    name    - the filename to expand
  250.  *
  251.  ***********************************************************************
  252.  */
  253.  
  254. char *
  255. ExpandFilename(name)
  256. char *name;
  257. {
  258.     char *newname;
  259.  
  260.     if (name[0] != '~') return name;
  261.  
  262.     newname = (char *) malloc (HomeLen + strlen(name) + 2);
  263.     if (!newname) {
  264.     fprintf (stderr, 
  265.          "%s:  unable to allocate %d bytes to expand filename %s/%s\n",
  266.          ProgramName, HomeLen + strlen(name) + 2, Home, &name[1]);
  267.     } else {
  268.     (void) sprintf (newname, "%s/%s", Home, &name[1]);
  269.     }
  270.  
  271.     return newname;
  272. }
  273.  
  274. /***********************************************************************
  275.  *
  276.  *  Procedure:
  277.  *    GetUnknownIcon - read in the bitmap file for the unknown icon
  278.  *
  279.  *  Inputs:
  280.  *    name - the filename to read
  281.  *
  282.  ***********************************************************************
  283.  */
  284.  
  285. void
  286. GetUnknownIcon(name)
  287. char *name;
  288. {
  289.     if ((Scr->UnknownPm = GetBitmap(name)) != None)
  290.     {
  291.     XGetGeometry(dpy, Scr->UnknownPm, &JunkRoot, &JunkX, &JunkY,
  292.         (unsigned int *)&Scr->UnknownWidth, (unsigned int *)&Scr->UnknownHeight, &JunkBW, &JunkDepth);
  293.     }
  294. }
  295.  
  296. /***********************************************************************
  297.  *
  298.  *  Procedure:
  299.  *    FindBitmap - read in a bitmap file and return size
  300.  *
  301.  *  Returned Value:
  302.  *    the pixmap associated with the bitmap
  303.  *      widthp    - pointer to width of bitmap
  304.  *      heightp    - pointer to height of bitmap
  305.  *
  306.  *  Inputs:
  307.  *    name    - the filename to read
  308.  *
  309.  ***********************************************************************
  310.  */
  311.  
  312. Pixmap FindBitmap (name, widthp, heightp)
  313.     char *name;
  314.     unsigned int *widthp, *heightp;
  315. {
  316.     char *bigname;
  317.     Pixmap pm;
  318.  
  319.     if (!name) return None;
  320.  
  321.     /*
  322.      * Names of the form :name refer to hardcoded images that are scaled to
  323.      * look nice in title buttons.  Eventually, it would be nice to put in a
  324.      * menu symbol as well....
  325.      */
  326.     if (name[0] == ':') {
  327.     int i;
  328.     static struct {
  329.         char *name;
  330.         Pixmap (*proc)();
  331.     } pmtab[] = {
  332.         { TBPM_DOT,        CreateDotPixmap },
  333.         { TBPM_ICONIFY,    CreateDotPixmap },
  334.         { TBPM_RESIZE,    CreateResizePixmap },
  335.         { TBPM_XLOGO,    CreateXLogoPixmap },
  336.         { TBPM_DELETE,    CreateXLogoPixmap },
  337.         { TBPM_MENU,    CreateMenuPixmap },
  338.         { TBPM_QUESTION,    CreateQuestionPixmap },
  339.     };
  340.     
  341.     for (i = 0; i < (sizeof pmtab)/(sizeof pmtab[0]); i++) {
  342.         if (XmuCompareISOLatin1 (pmtab[i].name, name) == 0)
  343.           return (*pmtab[i].proc) (widthp, heightp);
  344.     }
  345.     fprintf (stderr, "%s:  no such built-in bitmap \"%s\"\n",
  346.          ProgramName, name);
  347.     return None;
  348.     }
  349.  
  350.     /*
  351.      * Generate a full pathname if any special prefix characters (such as ~)
  352.      * are used.  If the bigname is different from name, bigname will need to
  353.      * be freed.
  354.      */
  355.     bigname = ExpandFilename (name);
  356.     if (!bigname) return None;
  357.  
  358.     /*
  359.      * look along bitmapFilePath resource same as toolkit clients
  360.      */
  361.     pm = XmuLocateBitmapFile (ScreenOfDisplay(dpy, Scr->screen), bigname, NULL,
  362.                   0, (int *)widthp, (int *)heightp, &HotX, &HotY);
  363.     if (pm == None && Scr->IconDirectory && bigname[0] != '/') {
  364.     if (bigname != name) free (bigname);
  365.     /*
  366.      * Attempt to find icon in old IconDirectory (now obsolete)
  367.      */
  368.     bigname = (char *) malloc (strlen(name) + strlen(Scr->IconDirectory) +
  369.                    2);
  370.     if (!bigname) {
  371.         fprintf (stderr,
  372.              "%s:  unable to allocate memory for \"%s/%s\"\n",
  373.              ProgramName, Scr->IconDirectory, name);
  374.         return None;
  375.     }
  376.     (void) sprintf (bigname, "%s/%s", Scr->IconDirectory, name);
  377.     if (XReadBitmapFile (dpy, Scr->Root, bigname, widthp, heightp, &pm,
  378.                  &HotX, &HotY) != BitmapSuccess) {
  379.         pm = None;
  380.     }
  381.     }
  382.     if (bigname != name) free (bigname);
  383.     if (pm == None) {
  384.     fprintf (stderr, "%s:  unable to find bitmap \"%s\"\n", 
  385.          ProgramName, name);
  386.     }
  387.  
  388.     return pm;
  389. }
  390.  
  391. Pixmap GetBitmap (name)
  392.     char *name;
  393. {
  394.     return FindBitmap (name, &JunkWidth, &JunkHeight);
  395. }
  396.  
  397.  
  398. InsertRGBColormap (a, maps, nmaps, replace)
  399.     Atom a;
  400.     XStandardColormap *maps;
  401.     int nmaps;
  402.     Bool replace;
  403. {
  404.     StdCmap *sc = NULL;
  405.  
  406.     if (replace) {            /* locate existing entry */
  407.     for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) {
  408.         if (sc->atom == a) break;
  409.     }
  410.     }
  411.  
  412.     if (!sc) {                /* no existing, allocate new */
  413.     sc = (StdCmap *) malloc (sizeof (StdCmap));
  414.     if (!sc) {
  415.         fprintf (stderr, "%s:  unable to allocate %d bytes for StdCmap\n",
  416.              ProgramName, sizeof (StdCmap));
  417.         return;
  418.     }
  419.     }
  420.  
  421.     if (replace) {            /* just update contents */
  422.     if (sc->maps) XFree ((char *) maps);
  423.     if (sc == Scr->StdCmapInfo.mru) Scr->StdCmapInfo.mru = NULL;
  424.     } else {                /* else appending */
  425.     sc->next = NULL;
  426.     sc->atom = a;
  427.     if (Scr->StdCmapInfo.tail) {
  428.         Scr->StdCmapInfo.tail->next = sc;
  429.     } else {
  430.         Scr->StdCmapInfo.head = sc;
  431.     }
  432.     Scr->StdCmapInfo.tail = sc;
  433.     }
  434.     sc->nmaps = nmaps;
  435.     sc->maps = maps;
  436.  
  437.     return;
  438. }
  439.  
  440. RemoveRGBColormap (a)
  441.     Atom a;
  442. {
  443.     StdCmap *sc, *prev;
  444.  
  445.     prev = NULL;
  446.     for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) {  
  447.     if (sc->atom == a) break;
  448.     prev = sc;
  449.     }
  450.     if (sc) {                /* found one */
  451.     if (sc->maps) XFree ((char *) sc->maps);
  452.     if (prev) prev->next = sc->next;
  453.     if (Scr->StdCmapInfo.head == sc) Scr->StdCmapInfo.head = sc->next;
  454.     if (Scr->StdCmapInfo.tail == sc) Scr->StdCmapInfo.tail = prev;
  455.     if (Scr->StdCmapInfo.mru == sc) Scr->StdCmapInfo.mru = NULL;
  456.     }
  457.     return;
  458. }
  459.  
  460. LocateStandardColormaps()
  461. {
  462.     Atom *atoms;
  463.     int natoms;
  464.     int i;
  465.  
  466.     atoms = XListProperties (dpy, Scr->Root, &natoms);
  467.     for (i = 0; i < natoms; i++) {
  468.     XStandardColormap *maps = NULL;
  469.     int nmaps;
  470.  
  471.     if (XGetRGBColormaps (dpy, Scr->Root, &maps, &nmaps, atoms[i])) {
  472.         /* if got one, then append to current list */
  473.         InsertRGBColormap (atoms[i], maps, nmaps, False);
  474.     }
  475.     }
  476.     if (atoms) XFree ((char *) atoms);
  477.     return;
  478. }
  479.  
  480. GetColor(kind, what, name)
  481. int kind;
  482. Pixel *what;
  483. char *name;
  484. {
  485.     XColor color, junkcolor;
  486.     Status stat = 0;
  487.     Colormap cmap = Scr->TwmRoot.cmaps.cwins[0]->colormap->c;
  488.  
  489. #ifndef TOM
  490.     if (!Scr->FirstTime)
  491.     return;
  492. #endif
  493.  
  494.     if (Scr->Monochrome != kind)
  495.     return;
  496.  
  497.     if (!XAllocNamedColor (dpy, cmap, name, &color, &junkcolor))
  498.     {
  499.     /* if we could not allocate the color, let's see if this is a
  500.      * standard colormap
  501.      */
  502.     XStandardColormap *stdcmap = NULL;
  503.  
  504.     /* parse the named color */
  505.     if (name[0] != '#')
  506.         stat = XParseColor (dpy, cmap, name, &color);
  507.     if (!stat)
  508.     {
  509.         fprintf (stderr, "%s:  invalid color name \"%s\"\n", 
  510.              ProgramName, name);
  511.         return;
  512.     }
  513.  
  514.     /*
  515.      * look through the list of standard colormaps (check cache first)
  516.      */
  517.     if (Scr->StdCmapInfo.mru && Scr->StdCmapInfo.mru->maps &&
  518.         (Scr->StdCmapInfo.mru->maps[Scr->StdCmapInfo.mruindex].colormap ==
  519.          cmap)) {
  520.         stdcmap = &(Scr->StdCmapInfo.mru->maps[Scr->StdCmapInfo.mruindex]);
  521.     } else {
  522.         StdCmap *sc;
  523.  
  524.         for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) {
  525.         int i;
  526.  
  527.         for (i = 0; i < sc->nmaps; i++) {
  528.             if (sc->maps[i].colormap == cmap) {
  529.             Scr->StdCmapInfo.mru = sc;
  530.             Scr->StdCmapInfo.mruindex = i;
  531.             stdcmap = &(sc->maps[i]);
  532.             goto gotit;
  533.             }
  534.         }
  535.         }
  536.     }
  537.  
  538.       gotit:
  539.     if (stdcmap) {
  540.             color.pixel = (stdcmap->base_pixel +
  541.                ((Pixel)(((float)color.red / 65535.0) *
  542.                     stdcmap->red_max + 0.5) *
  543.                 stdcmap->red_mult) +
  544.                ((Pixel)(((float)color.green /65535.0) *
  545.                     stdcmap->green_max + 0.5) *
  546.                 stdcmap->green_mult) +
  547.                ((Pixel)(((float)color.blue  / 65535.0) *
  548.                     stdcmap->blue_max + 0.5) *
  549.                 stdcmap->blue_mult));
  550.         } else {
  551.         fprintf (stderr, "%s:  unable to allocate color \"%s\"\n", 
  552.              ProgramName, name);
  553.         return;
  554.     }
  555.     }
  556.  
  557.     *what = color.pixel;
  558. }
  559.  
  560. GetFont(font)
  561. MyFont *font;
  562. {
  563.     char *deffontname = "fixed";
  564.  
  565.     if (font->font != NULL)
  566.     XFreeFont(dpy, font->font);
  567.  
  568.     if ((font->font = XLoadQueryFont(dpy, font->name)) == NULL)
  569.     {
  570.     if (Scr->DefaultFont.name) {
  571.         deffontname = Scr->DefaultFont.name;
  572.     }
  573.     if ((font->font = XLoadQueryFont(dpy, deffontname)) == NULL)
  574.     {
  575.         fprintf (stderr, "%s:  unable to open fonts \"%s\" or \"%s\"\n",
  576.              ProgramName, font->name, deffontname);
  577.         exit(1);
  578.     }
  579.  
  580.     }
  581.     font->height = font->font->ascent + font->font->descent;
  582.     font->y = font->font->ascent;
  583. }
  584.  
  585.  
  586. /*
  587.  * SetFocus - separate routine to set focus to make things more understandable
  588.  * and easier to debug
  589.  */
  590. SetFocus (tmp_win, time)
  591.     TwmWindow *tmp_win;
  592.     Time    time;
  593. {
  594.     Window w = (tmp_win ? tmp_win->w : PointerRoot);
  595.  
  596. #ifdef TRACE
  597.     if (tmp_win) {
  598.     printf ("Focusing on window \"%s\"\n", tmp_win->full_name);
  599.     } else {
  600.     printf ("Unfocusing; Scr->Focus was \"%s\"\n",
  601.         Scr->Focus ? Scr->Focus->full_name : "(nil)");
  602.     }
  603. #endif
  604.  
  605.     XSetInputFocus (dpy, w, RevertToPointerRoot, time);
  606. }
  607.  
  608.  
  609. #ifdef NOPUTENV
  610. /*
  611.  * define our own putenv() if the system doesn't have one.
  612.  * putenv(s): place s (a string of the form "NAME=value") in
  613.  * the environment; replacing any existing NAME.  s is placed in
  614.  * environment, so if you change s, the environment changes (like
  615.  * putenv on a sun).  Binding removed if you putenv something else
  616.  * called NAME.
  617.  */
  618. int
  619. putenv(s)
  620.     char *s;
  621. {
  622.     char *v;
  623.     int varlen, idx;
  624.     extern char **environ;
  625.     char **newenv;
  626.     static int virgin = 1; /* true while "environ" is a virgin */
  627.  
  628.     v = index(s, '=');
  629.     if(v == 0)
  630.     return 0; /* punt if it's not of the right form */
  631.     varlen = (v + 1) - s;
  632.  
  633.     for (idx = 0; environ[idx] != 0; idx++) {
  634.     if (strncmp(environ[idx], s, varlen) == 0) {
  635.         if(v[1] != 0) { /* true if there's a value */
  636.         environ[idx] = s;
  637.         return 0;
  638.         } else {
  639.         do {
  640.             environ[idx] = environ[idx+1];
  641.         } while(environ[++idx] != 0);
  642.         return 0;
  643.         }
  644.     }
  645.     }
  646.     
  647.     /* add to environment (unless no value; then just return) */
  648.     if(v[1] == 0)
  649.     return 0;
  650.     if(virgin) {
  651.     register i;
  652.  
  653.     newenv = (char **) malloc((unsigned) ((idx + 2) * sizeof(char*)));
  654.     if(newenv == 0)
  655.         return -1;
  656.     for(i = idx-1; i >= 0; --i)
  657.         newenv[i] = environ[i];
  658.     virgin = 0;     /* you're not a virgin anymore, sweety */
  659.     } else {
  660.     newenv = (char **) realloc((char *) environ,
  661.                    (unsigned) ((idx + 2) * sizeof(char*)));
  662.     if (newenv == 0)
  663.         return -1;
  664.     }
  665.  
  666.     environ = newenv;
  667.     environ[idx] = s;
  668.     environ[idx+1] = 0;
  669.     
  670.     return 0;
  671. }
  672. #endif /* NOPUTENV */
  673.  
  674.  
  675. static Pixmap CreateXLogoPixmap (widthp, heightp)
  676.     unsigned int *widthp, *heightp;
  677. {
  678.     int h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
  679.     if (h < 0) h = 0;
  680.  
  681.     *widthp = *heightp = (unsigned int) h;
  682.     if (Scr->tbpm.xlogo == None) {
  683.     GC gc, gcBack;
  684.  
  685.     Scr->tbpm.xlogo = XCreatePixmap (dpy, Scr->Root, h, h, 1);
  686.     gc = XCreateGC (dpy, Scr->tbpm.xlogo, 0L, NULL);
  687.     XSetForeground (dpy, gc, 0);
  688.     XFillRectangle (dpy, Scr->tbpm.xlogo, gc, 0, 0, h, h);
  689.     XSetForeground (dpy, gc, 1);
  690.     gcBack = XCreateGC (dpy, Scr->tbpm.xlogo, 0L, NULL);
  691.     XSetForeground (dpy, gcBack, 0);
  692.  
  693.     /*
  694.      * draw the logo large so that it gets as dense as possible; then white
  695.      * out the edges so that they look crisp
  696.      */
  697.     XmuDrawLogo (dpy, Scr->tbpm.xlogo, gc, gcBack, -1, -1, h + 2, h + 2);
  698.     XDrawRectangle (dpy, Scr->tbpm.xlogo, gcBack, 0, 0, h - 1, h - 1);
  699.  
  700.     /*
  701.      * done drawing
  702.      */
  703.     XFreeGC (dpy, gc);
  704.     XFreeGC (dpy, gcBack);
  705.     }
  706.     return Scr->tbpm.xlogo;
  707. }
  708.  
  709.  
  710. static Pixmap CreateResizePixmap (widthp, heightp)
  711.     unsigned int *widthp, *heightp;
  712. {
  713.     int h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
  714.     if (h < 1) h = 1;
  715.  
  716.     *widthp = *heightp = (unsigned int) h;
  717.     if (Scr->tbpm.resize == None) {
  718.     XPoint    points[3];
  719.     GC gc;
  720.     int w;
  721.     int lw;
  722.  
  723.     /*
  724.      * create the pixmap
  725.      */
  726.     Scr->tbpm.resize = XCreatePixmap (dpy, Scr->Root, h, h, 1);
  727.     gc = XCreateGC (dpy, Scr->tbpm.resize, 0L, NULL);
  728.     XSetForeground (dpy, gc, 0);
  729.     XFillRectangle (dpy, Scr->tbpm.resize, gc, 0, 0, h, h);
  730.     XSetForeground (dpy, gc, 1);
  731.     lw = h / 16;
  732.     if (lw == 1)
  733.         lw = 0;
  734.     XSetLineAttributes (dpy, gc, lw, LineSolid, CapButt, JoinMiter);
  735.  
  736.     /*
  737.      * draw the resize button, 
  738.      */
  739.     w = (h * 2) / 3;
  740.     points[0].x = w;
  741.     points[0].y = 0;
  742.     points[1].x = w;
  743.     points[1].y = w;
  744.     points[2].x = 0;
  745.     points[2].y = w;
  746.     XDrawLines (dpy, Scr->tbpm.resize, gc, points, 3, CoordModeOrigin);
  747.     w = w / 2;
  748.     points[0].x = w;
  749.     points[0].y = 0;
  750.     points[1].x = w;
  751.     points[1].y = w;
  752.     points[2].x = 0;
  753.     points[2].y = w;
  754.     XDrawLines (dpy, Scr->tbpm.resize, gc, points, 3, CoordModeOrigin);
  755.  
  756.     /*
  757.      * done drawing
  758.      */
  759.     XFreeGC(dpy, gc);
  760.     }
  761.     return Scr->tbpm.resize;
  762. }
  763.  
  764.  
  765. static Pixmap CreateDotPixmap (widthp, heightp)
  766.     unsigned int *widthp, *heightp;
  767. {
  768.     int h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
  769.  
  770.     h = h * 3 / 4;
  771.     if (h < 1) h = 1;
  772.     if (!(h & 1))
  773.     h--;
  774.     *widthp = *heightp = (unsigned int) h;
  775.     if (Scr->tbpm.delete == None) {
  776.     GC  gc;
  777.     Pixmap pix;
  778.  
  779.     pix = Scr->tbpm.delete = XCreatePixmap (dpy, Scr->Root, h, h, 1);
  780.     gc = XCreateGC (dpy, pix, 0L, NULL);
  781.     XSetLineAttributes (dpy, gc, h, LineSolid, CapRound, JoinRound);
  782.     XSetForeground (dpy, gc, 0L);
  783.     XFillRectangle (dpy, pix, gc, 0, 0, h, h);
  784.     XSetForeground (dpy, gc, 1L);
  785.     XDrawLine (dpy, pix, gc, h/2, h/2, h/2, h/2);
  786.     XFreeGC (dpy, gc);
  787.     }
  788.     return Scr->tbpm.delete;
  789. }
  790.  
  791. #define questionmark_width 8
  792. #define questionmark_height 8
  793. static char questionmark_bits[] = {
  794.    0x38, 0x7c, 0x64, 0x30, 0x18, 0x00, 0x18, 0x18};
  795.  
  796. static Pixmap CreateQuestionPixmap (widthp, heightp)
  797.     unsigned int *widthp, *heightp;
  798. {
  799.     *widthp = questionmark_width;
  800.     *heightp = questionmark_height;
  801.     if (Scr->tbpm.question == None) {
  802.     Scr->tbpm.question = XCreateBitmapFromData (dpy, Scr->Root,
  803.                             questionmark_bits,
  804.                             questionmark_width,
  805.                             questionmark_height);
  806.     }
  807.     /*
  808.      * this must succeed or else we are in deep trouble elsewhere
  809.      */
  810.     return Scr->tbpm.question;
  811. }
  812.  
  813.  
  814. static Pixmap CreateMenuPixmap (widthp, heightp)
  815.     int *widthp, *heightp;
  816. {
  817.     CreateMenuIcon (Scr->TBInfo.width - Scr->TBInfo.border * 2,widthp,heightp);
  818. }
  819.  
  820. Pixmap CreateMenuIcon (height, widthp, heightp)
  821.     int    height;
  822.     int    *widthp, *heightp;
  823. {
  824.     int h, w;
  825.     int ih, iw;
  826.     int    ix, iy;
  827.     int    mh, mw;
  828.     int    tw, th;
  829.     int    lw, lh;
  830.     int    lx, ly;
  831.     int    lines, dly;
  832.     int off;
  833.     int    bw;
  834.  
  835.     h = height;
  836.     w = h * 7 / 8;
  837.     if (h < 1)
  838.     h = 1;
  839.     if (w < 1)
  840.     w = 1;
  841.     *widthp = w;
  842.     *heightp = h;
  843.     if (Scr->tbpm.menu == None) {
  844.     Pixmap  pix;
  845.     GC    gc;
  846.  
  847.     pix = Scr->tbpm.menu = XCreatePixmap (dpy, Scr->Root, w, h, 1);
  848.     gc = XCreateGC (dpy, pix, 0L, NULL);
  849.     XSetForeground (dpy, gc, 0L);
  850.     XFillRectangle (dpy, pix, gc, 0, 0, w, h);
  851.     XSetForeground (dpy, gc, 1L);
  852.     ix = 1;
  853.     iy = 1;
  854.     ih = h - iy * 2;
  855.     iw = w - ix * 2;
  856.     off = ih / 8;
  857.     mh = ih - off;
  858.     mw = iw - off;
  859.     bw = mh / 16;
  860.     if (bw == 0 && mw > 2)
  861.         bw = 1;
  862.     tw = mw - bw * 2;
  863.     th = mh - bw * 2;
  864.     XFillRectangle (dpy, pix, gc, ix, iy, mw, mh);
  865.     XFillRectangle (dpy, pix, gc, ix + iw - mw, iy + ih - mh, mw, mh);
  866.     XSetForeground (dpy, gc, 0L);
  867.     XFillRectangle (dpy, pix, gc, ix+bw, iy+bw, tw, th);
  868.     XSetForeground (dpy, gc, 1L);
  869.     lw = tw / 2;
  870.     if ((tw & 1) ^ (lw & 1))
  871.         lw++;
  872.     lx = ix + bw + (tw - lw) / 2;
  873.  
  874.     lh = th / 2 - bw;
  875.     if ((lh & 1) ^ ((th - bw) & 1))
  876.         lh++;
  877.     ly = iy + bw + (th - bw - lh) / 2;
  878.  
  879.     lines = 3;
  880.     if ((lh & 1) && lh < 6)
  881.     {
  882.         lines--;
  883.     }
  884.     dly = lh / (lines - 1);
  885.     while (lines--)
  886.     {
  887.         XFillRectangle (dpy, pix, gc, lx, ly, lw, bw);
  888.         ly += dly;
  889.     }
  890.     XFreeGC (dpy, gc);
  891.     }
  892.     return Scr->tbpm.menu;
  893. }
  894.